import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Query,
  Body,
  UseInterceptors,
  UploadedFile,
  Res,
  Request,
  ParseFilePipe,
  MaxFileSizeValidator,
  FileTypeValidator,
} from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { Response } from 'express'
import {
  ApiTags,
  ApiOperation,
  ApiConsumes,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiResponse,
  ApiBearerAuth,
} from '@nestjs/swagger'
import { createReadStream, existsSync } from 'fs'
import { FileService } from '../services/file.service'
import { UploadFileDto, UploadFileResponseDto } from '../dto/upload-file.dto'
import { QueryFileDto } from '../dto/query-file.dto'
import { UpdateFileDto } from '../dto/query-file.dto'
import { Permissions } from 'src/common/decorators/permissions.decorator'
import { Payload } from 'src/common/interfaces/auth.interface'

/**
 * 文件管理控制器
 * 提供文件上传、下载、查询、管理等功能的RESTful API
 */
@ApiTags('文件管理')
@Controller('files')
@ApiBearerAuth()
export class FileController {
  constructor(private readonly fileService: FileService) {}

  /**
   * 上传文件
   * 支持单文件上传，自动生成唯一文件名，支持文件去重
   */
  @Post('upload')
  @ApiOperation({
    summary: '上传文件',
    description: '上传单个文件，支持文件去重和权限控制',
  })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    description: '文件上传表单',
    schema: {
      type: 'object',
      properties: {
        file: {
          type: 'string',
          format: 'binary',
          description: '要上传的文件',
        },
        description: {
          type: 'string',
          description: '文件描述',
        },
        tags: {
          type: 'array',
          items: { type: 'string' },
          description: '文件标签',
        },
        isPublic: {
          type: 'boolean',
          description: '是否公开访问',
        },
        readPermissions: {
          type: 'array',
          items: { type: 'string' },
          description: '可读权限用户ID列表',
        },
        writePermissions: {
          type: 'array',
          items: { type: 'string' },
          description: '可写权限用户ID列表',
        },
        deletePermissions: {
          type: 'array',
          items: { type: 'string' },
          description: '可删除权限用户ID列表',
        },
      },
    },
  })
  @ApiResponse({
    status: 201,
    description: '文件上传成功',
    type: UploadFileResponseDto,
  })
  @ApiResponse({
    status: 400,
    description: '文件格式不支持或大小超限',
  })
  @ApiResponse({
    status: 401,
    description: '未授权',
  })
  @UseInterceptors(FileInterceptor('file'))
  @Permissions('file:upload')
  async uploadFile(
    @UploadedFile(
      new ParseFilePipe({
        validators: [
          new MaxFileSizeValidator({ maxSize: 100 * 1024 * 1024 }), // 100MB
          new FileTypeValidator({ fileType: /(jpg|jpeg|png|gif|pdf|doc|docx|xls|xlsx|txt|zip|rar)$/ }),
        ],
      }),
    )
    file: Express.Multer.File,
    @Body() uploadData: UploadFileDto,
    @Request() req: { user: Payload } & Request,
  ): Promise<UploadFileResponseDto> {
    const uploadedFile = await this.fileService.uploadFile(file, uploadData, req.user.id)

    return {
      id: uploadedFile.id,
      originalName: uploadedFile.originalName,
      filename: uploadedFile.filename,
      size: uploadedFile.size,
      mimeType: uploadedFile.mimeType,
      url: uploadedFile.url,
      status: uploadedFile.status,
    }
  }

  /**
   * 获取文件列表
   * 支持分页、搜索、筛选、排序等功能
   */
  @Get()
  @ApiOperation({
    summary: '获取文件列表',
    description: '获取文件列表，支持分页、搜索、筛选、排序等功能',
  })
  @ApiQuery({ name: 'page', required: false, description: '页码', example: 1 })
  @ApiQuery({ name: 'limit', required: false, description: '每页数量', example: 10 })
  @ApiQuery({ name: 'search', required: false, description: '搜索关键词' })
  @ApiQuery({ name: 'category', required: false, description: '文件分类' })
  @ApiQuery({ name: 'mimeType', required: false, description: 'MIME类型' })
  @ApiQuery({ name: 'status', required: false, description: '文件状态' })
  @ApiQuery({ name: 'isPublic', required: false, description: '是否公开' })
  @ApiQuery({ name: 'tags', required: false, description: '文件标签' })
  @ApiQuery({ name: 'uploaderId', required: false, description: '上传者ID' })
  @ApiQuery({ name: 'minSize', required: false, description: '最小文件大小' })
  @ApiQuery({ name: 'maxSize', required: false, description: '最大文件大小' })
  @ApiQuery({ name: 'startDate', required: false, description: '开始日期' })
  @ApiQuery({ name: 'endDate', required: false, description: '结束日期' })
  @ApiQuery({ name: 'sortBy', required: false, description: '排序字段' })
  @ApiQuery({ name: 'sortOrder', required: false, description: '排序方向' })
  @ApiResponse({
    status: 200,
    description: '获取文件列表成功',
    schema: {
      type: 'object',
      properties: {
        data: {
          type: 'array',
          items: { $ref: '#/components/schemas/File' },
        },
        total: {
          type: 'number',
          description: '总数量',
        },
      },
    },
  })
  @Permissions('file:read')
  async getFiles(
    @Query() query: QueryFileDto,
    @Request() req: { user: Payload } & Request,
  ): Promise<{ data: any[]; total: number }> {
    return this.fileService.getFiles(query, req.user.id)
  }

  /**
   * 根据ID获取文件信息
   */
  @Get(':id')
  @ApiOperation({
    summary: '获取文件信息',
    description: '根据文件ID获取文件详细信息',
  })
  @ApiParam({ name: 'id', description: '文件ID' })
  @ApiResponse({
    status: 200,
    description: '获取文件信息成功',
    schema: { $ref: '#/components/schemas/File' },
  })
  @ApiResponse({
    status: 404,
    description: '文件不存在',
  })
  @ApiResponse({
    status: 403,
    description: '没有访问权限',
  })
  @Permissions('file:read')
  async getFileById(@Param('id') id: number, @Request() req: { user: Payload } & Request): Promise<any> {
    return this.fileService.getFileById(id, req.user.id)
  }

  /**
   * 下载文件
   * 根据文件名直接下载文件
   */
  @Get('download/:filename')
  @ApiOperation({
    summary: '下载文件',
    description: '根据文件名下载文件',
  })
  @ApiParam({ name: 'filename', description: '文件名' })
  @ApiResponse({
    status: 200,
    description: '文件下载成功',
  })
  @ApiResponse({
    status: 404,
    description: '文件不存在',
  })
  @ApiResponse({
    status: 403,
    description: '没有访问权限',
  })
  @Permissions('file:download')
  async downloadFile(
    @Param('filename') filename: string,
    @Res() res: Response,
    @Request() req: { user: Payload } & Request,
  ): Promise<void> {
    const file = await this.fileService.getFileByFilename(filename, req.user.id)

    if (!existsSync(file.path)) {
      res.status(404).json({ message: '文件不存在' })
      return
    }

    res.setHeader('Content-Type', file.mimeType)
    res.setHeader('Content-Disposition', `attachment; filename="${file.originalName}"`)

    const fileStream = createReadStream(file.path)
    fileStream.pipe(res)
  }

  /**
   * 更新文件信息
   */
  @Put(':id')
  @ApiOperation({
    summary: '更新文件信息',
    description: '更新文件的描述、标签、权限等信息',
  })
  @ApiParam({ name: 'id', description: '文件ID' })
  @ApiBody({ type: UpdateFileDto })
  @ApiResponse({
    status: 200,
    description: '更新成功',
    schema: { $ref: '#/components/schemas/File' },
  })
  @ApiResponse({
    status: 404,
    description: '文件不存在',
  })
  @ApiResponse({
    status: 403,
    description: '没有修改权限',
  })
  @Permissions('file:update')
  async updateFile(
    @Param('id') id: number,
    @Body() updateData: UpdateFileDto,
    @Request() req: { user: Payload } & Request,
  ): Promise<any> {
    return this.fileService.updateFile(id, updateData, req.user.id)
  }

  /**
   * 删除文件
   */
  @Delete(':id')
  @ApiOperation({
    summary: '删除文件',
    description: '删除指定文件（包括物理文件和数据库记录）',
  })
  @ApiParam({ name: 'id', description: '文件ID' })
  @ApiResponse({
    status: 200,
    description: '删除成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
      },
    },
  })
  @ApiResponse({
    status: 404,
    description: '文件不存在',
  })
  @ApiResponse({
    status: 403,
    description: '没有删除权限',
  })
  @Permissions('file:delete')
  async deleteFile(
    @Param('id') id: number,
    @Request() req: { user: Payload } & Request,
  ): Promise<{ success: boolean }> {
    return this.fileService.deleteFile(id, req.user.id)
  }

  /**
   * 批量删除文件
   */
  @Delete('batch/delete')
  @ApiOperation({
    summary: '批量删除文件',
    description: '批量删除多个文件',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        ids: {
          type: 'array',
          items: { type: 'string' },
          description: '要删除的文件ID列表',
        },
      },
    },
  })
  @ApiResponse({
    status: 200,
    description: '批量删除成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        deletedCount: { type: 'number' },
      },
    },
  })
  @Permissions('file:delete')
  async deleteFiles(
    @Body() body: { ids: number[] },
    @Request() req: { user: Payload } & Request,
  ): Promise<{ success: boolean; deletedCount: number }> {
    return this.fileService.deleteFiles(body.ids, req.user.id)
  }

  /**
   * 获取文件统计信息
   */
  @Get('stats/overview')
  @ApiOperation({
    summary: '获取文件统计信息',
    description: '获取文件总数、总大小、分类统计等信息',
  })
  @ApiResponse({
    status: 200,
    description: '获取统计信息成功',
    schema: {
      type: 'object',
      properties: {
        totalFiles: { type: 'number' },
        totalSize: { type: 'number' },
        avgSize: { type: 'number' },
        categoryCount: { type: 'number' },
        uploaderCount: { type: 'number' },
        categoryStats: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              category: { type: 'string' },
              count: { type: 'number' },
              totalSize: { type: 'number' },
            },
          },
        },
      },
    },
  })
  @Permissions('file:read')
  async getFileStats(@Request() req: { user: Payload } & Request): Promise<any> {
    return this.fileService.getFileStats(req.user.id)
  }

  /**
   * 获取支持的文件类型
   */
  @Get('types/supported')
  @ApiOperation({
    summary: '获取支持的文件类型',
    description: '获取系统支持上传的文件类型列表',
  })
  @ApiResponse({
    status: 200,
    description: '获取支持的文件类型成功',
    schema: {
      type: 'object',
      properties: {
        maxFileSize: { type: 'number', description: '最大文件大小（字节）' },
        allowedMimeTypes: {
          type: 'array',
          items: { type: 'string' },
          description: '支持的MIME类型列表',
        },
        categories: {
          type: 'object',
          description: '文件分类说明',
        },
      },
    },
  })
  @Permissions('file:types')
  getSupportedFileTypes() {
    return {
      maxFileSize: 100 * 1024 * 1024, // 100MB
      allowedMimeTypes: [
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/webp',
        'image/svg+xml',
        'application/pdf',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'text/plain',
        'text/csv',
        'video/mp4',
        'video/avi',
        'video/mov',
        'video/wmv',
        'audio/mpeg',
        'audio/wav',
        'audio/ogg',
        'application/zip',
        'application/x-rar-compressed',
        'application/x-7z-compressed',
      ],
      categories: {
        image: '图片文件（JPEG、PNG、GIF、WebP、SVG）',
        video: '视频文件（MP4、AVI、MOV、WMV）',
        audio: '音频文件（MP3、WAV、OGG）',
        document: '文档文件（PDF、Word、Excel、TXT、CSV）',
        archive: '压缩文件（ZIP、RAR、7Z）',
        other: '其他文件类型',
      },
    }
  }
}
